package com.rzjm.api.netty.water.business.inhandler;

import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.rzjm.api.entity.DeviceWater;
import com.rzjm.api.entity.DeviceWaterOrder;
import com.rzjm.api.netty.water.NettyUtil;
import com.rzjm.api.netty.water.entity.ReceiveData;
import com.rzjm.api.service.IDeviceWaterMessagesService;
import com.rzjm.api.service.IDeviceWaterOrderService;
import com.rzjm.api.service.IDeviceWaterService;
import com.rzjm.api.util.*;
import io.netty.channel.ChannelHandlerContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.Date;
import java.util.Optional;

import static com.rzjm.api.netty.water.constant.SendRtEnum.SEND_RT_3;
import static com.rzjm.api.util.DateUtils.localDateTimeStartToSecond;

/**
 *  取水完成
 * @author Mr.Zhou
 * @Description:
 * @date 2025/3/17 9:27
 */
@Component
public class Receive3InHandler implements InHandler {
    private static final Logger LOGGER = LoggerFactory.getLogger(Receive3InHandler.class);
    @Autowired
    private IDeviceWaterService devicesService;
    @Autowired
    private IDeviceWaterMessagesService deviceMessagesService;
    @Autowired
    private IDeviceWaterOrderService waterOrderService;

    @Override
    public void handler(ChannelHandlerContext ctx, ReceiveData receiveData) {
        //保存Channel
        NettyUtil.addChannel(ctx, receiveData.getId());
        // 保存上报数据日志
        Optional.ofNullable(getMessage(receiveData))
                .ifPresent(message -> deviceMessagesService.save(message));

        DeviceWater deviceWater = devicesService.findById(receiveData.getId());


        if(StrUtil.isNotEmpty(receiveData.getV5())){
            long timespan = Long.parseLong(receiveData.getV5());
            Date validTime = new Date(timespan);
            System.out.println("validTime = " + validTime);
            //5分钟之后的时间
            Date checkTime = DateUtils.getAfterSecondsByOld(validTime, 5 * 50);
            // 如果当前时间大于请求的5分钟之后的时间  就不能再执行当前操作，需要重新发起
            if(new Date().getTime() > checkTime.getTime()){
                //订单超时
                reply("{\"rt\":3,\"type\":3,\"v1\":\""+receiveData.getV1()+"\",\"v2\":3}", receiveData.getId());
            }else{
                String crcType = "03";
                String crcMoney = "";

                if(receiveData.getV2().length() < 2){
                    crcMoney = "0" + crcMoney;
                }else{
                    crcMoney = receiveData.getV2().substring(receiveData.getV2().length() - 2, receiveData.getV2().length());//使用金额
                    System.out.println("type 3: crcMoney  = " + crcMoney);
                    crcMoney = ByteUtil.int2Hex(Integer.parseInt(crcMoney));
                }
                if(crcMoney.length() % 2 == 1){
                    crcMoney = "0" + crcMoney;
                }

                System.out.println("type 3: crcMoney 16进制  = " + crcMoney);
                String orderNo = receiveData.getV1().substring(receiveData.getV1().length() - 2, receiveData.getV1().length());//订单号
                System.out.println("type 3: orderNo  = " + orderNo);
                orderNo = ByteUtil.int2Hex(Integer.parseInt(orderNo));
                if(orderNo.length() % 2 == 1){
                    orderNo = "0" + orderNo;
                }
                System.out.println("type 3: orderNo  16进制  = " + orderNo);
                String crc = getSignCrc(crcType, crcMoney, orderNo);
                System.out.println("type 3: crc 计算的校验值 = " + crc);
                System.out.println("type 3: crc 上传过来的校验值 = " + receiveData.getV4());

                boolean bl = true;
//                if(crc.equals(receiveData.getV4())){
//                    bl = true;
//                    System.out.println("type 3: 验证成功 ： " + crc);
//                }
                if(bl){
                    //回复消息
                    String replyData = requestData(deviceWater, receiveData);
                    if (StrUtil.isNotEmpty(replyData)) {
                        reply(replyData, receiveData.getId());
                    }
                }else{
                    System.out.println("type 3: crc 验证失败 ");
                    reply("{\"rt\":100,\"type\":3}", receiveData.getId());
                }
            }

        }else{
            System.out.println("订单处理失败，没有上传时间戳");
            reply("{\"rt\":3,\"type\":3,\"v1\":\""+receiveData.getV1()+"\",\"v2\":2}", receiveData.getId());
        }

    }

    /**
     * 取水完成 拼装数据
     * @param device
     * @param receiveData
     * @return
     */
    private String requestData(DeviceWater device, ReceiveData receiveData) {

        System.out.println("取水完成数据上报请求：" + JSONUtil.toJsonStr(receiveData));
        String replyData;
        // 当日开始时间的总秒数
        long startSecond = localDateTimeStartToSecond();
        JSONObject obj = JSONUtil.createObj();

        obj = JSONUtil.createObj();
        obj.set("rt", SEND_RT_3.getRt());
        obj.set("v1", receiveData.getV1());// 订单号

        QueryWrapper<DeviceWaterOrder> qw = new QueryWrapper<>();
        qw.eq("order_no", receiveData.getV1());
        qw.last("limit 1");
        DeviceWaterOrder waterOrder = waterOrderService.getOne(qw);
        if(waterOrder == null){
            obj.set("v2", 1);// 订单不存在
        }else{
            if(waterOrder.getStatus() == 2){
                int ret = waterOrderService.overOrderByCard(device, waterOrder, receiveData);
                if(ret > 0){
                    obj.set("v2", 0);// 订单成功
                }else{
                    obj.set("v2", 2);// 处理失败
                }
            }else{
                if(waterOrder.getStatus() == 7){
                    obj.set("v2", 0);// 订单成功
                }else{
                    obj.set("v2", 0);// 订单成功
                }
            }
        }

        replyData = JSONUtil.toJsonStr(obj);
        return replyData;
    }


    /**
     * 获取签名 crc校验
     * @param v2
     * @param money
     * @param orderNo
     * @return
     */
    private String getSignCrc(String v2, String money, String orderNo){

        //低位在前，CRC校验3个字节，RT+剩余金额后两位+时间戳后两位
//        例：RT：02
//        金额：91=0x5B
//        时间戳64=0x40
//        结果：EAC0
        String crcData = v2 + money + orderNo;
        System.out.println("校验串： " + crcData);
        String crc = CRCUtil.getCrc(crcData);
        return crc;
    }

}
